home *** CD-ROM | disk | FTP | other *** search
- ╒═══════════════════════════════╕
- │ W E L C O M E │
- │ To the VGA Trainer Program │ │
- │ By │ │
- │ DENTHOR of ASPHYXIA │ │ │
- ╘═══════════════════════════════╛ │ │
- ────────────────────────────────┘ │
- ────────────────────────────────┘
-
- --==[ PART 7 ]==--
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Introduction
-
- Hello! By popular request, this part is all about animation. I will be
- going over three methods of doing animation on a PC, and will
- concerntrate specifically on one, which will be demonstrated in the
- attached sample code.
-
- Although not often used in demo coding, animation is usually used in
- games coding, which can be almost as rewarding ;-)
-
- In this part I will also be a lot less stingy with assembler code :)
- Included will be a fairly fast pure assembler putpixel, an asm screen
- flip command, an asm icon placer, an asm partial-flip and one or two
- others. I will be explaining how these work in detail, so this may also
- be used as a bit of an asm-trainer too.
-
- By the way, I apologise for this part taking so long to be released, but
- I only finished my exams a few days ago, and they of course took
- preference ;-). I have also noticed that the MailBox BBS is no longer
- operational, so the trainer will be uploaded regularly to the BBS lists
- shown at the end of this tutorial.
-
- If you would like to contact me, or the team, there are many ways you
- can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
- on the ASPHYXIA BBS.
- 2) Write a message in the Programming conference on the
- For Your Eyes Only BBS (of which I am the Moderator )
- This is preferred if you have a general programming query
- or problem others would benefit from.
- 4) Write to Denthor, Eze or Livewire on Connectix.
- 5) Write to : Grant Smith
- P.O.Box 270 Kloof
- 3640
- Natal
- 6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
- call during varsity)
- 7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
- mention the word Denthor near the top of the letter.
-
- NB : If you are a representative of a company or BBS, and want ASPHYXIA
- to do you a demo, leave mail to me; we can discuss it.
- NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
- quite lonely and want to meet/help out/exchange code with other demo
- groups. What do you have to lose? Leave a message here and we can work
- out how to transfer it. We really want to hear from you!
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ The Principals of Animation
-
- I am sure all of you have seen a computer game with animation at one or
- other time. There are a few things that an animation sequence must do in
- order to give an impression of realism. Firstly, it must move,
- preferably using different frames to add to the realism (for example,
- with a man walking you should have different frames with the arms an
- legs in different positions). Secondly, it must not destroy the
- background, but restore it after it has passed over it.
-
- This sounds obvious enough, but can be very difficult to code when you
- have no idea of how to go about achieving that.
-
- In this trainer I will discuss various methods of meeting these two
- objectives.
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Frames and Object Control
-
- It is quite obvious that for most animation to succeed, you must have
- numerous frames of the object in various poses (such as a man with
- several frames of him walking). When shown one after the other, these
- give the impression of natural movement.
-
- So, how do we store these frames? I hear you cry. Well, the obvious
- method is to store them in arrays. After drawing a frame in Autodesk
- Animator and saving it as a .CEL, we usually use the following code to
- load it in :
-
- TYPE icon = Array [1..50,1..50] of byte;
-
- VAR tree : icon;
-
- Procedure LoadCEL (FileName : string; ScrPtr : pointer);
- var
- Fil : file;
- Buf : array [1..1024] of byte;
- BlocksRead, Count : word;
- begin
- assign (Fil, FileName);
- reset (Fil, 1);
- BlockRead (Fil, Buf, 800); { Read and ignore the 800 byte header }
- Count := 0; BlocksRead := $FFFF;
- while (not eof (Fil)) and (BlocksRead <> 0) do begin
- BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
- Count := Count + 1024;
- end;
- close (Fil);
- end;
-
- BEGIN
- Loadcel ('Tree.CEL',addr (tree));
- END.
-
- We now have the 50x50 picture of TREE.CEL in our array tree. We may access
- this array in the usual manner (eg. col:=tree [25,30]). If the frame is
- large, or if you have many frames, try using pointers (see previous
- parts)
-
- Now that we have the picture, how do we control the object? What if we
- want multiple trees wandering around doing their own thing? The solution
- is to have a record of information for each tree. A typical data
- structure may look like the following :
-
- TYPE Treeinfo = Record
- x,y:word; { Where the tree is }
- speed:byte; { How fast the tree is moving }
- Direction:byte; { Where the tree is facing }
- frame:byte { Which animation frame the tree is
- currently involved in }
- active:boolean; { Is the tree actually supposed to be
- shown/used? }
- END;
-
- VAR Forest : Array [1..20] of Treeinfo;
-
- You now have 20 trees, each with their own information, location etc.
- These are accessed using the following means :
- Forest [15].x:=100;
- This would set the 15th tree's x coordinate to 100.
-
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ Restoring the Overwritten Background
-
- I will discuss three methods of doing this. These are NOT NECESSARILY
- THE ONLY OR BEST WAYS TO DO THIS! You must experiment and decide which
- is the best for your particular type of program.
-
- METHOD 1 :
-
- Step 1 : Create two virtual pages, Vaddr and Vaddr2.
- Step 2 : Draw the background to Vaddr2.
- Step 3 : Flip Vaddr2 to Vaddr.
- Step 4 : Draw all the foreground objects onto Vaddr.
- Step 5 : Flip Vaddr to VGA.
- Step 6 : Repeat from 3 continuously.
-
- In ascii, it looks like follows ...
-
- +---------+ +---------+ +---------+
- | | | | | |
- | VGA | <======= | VADDR | <====== | VADDR2 |
- | | | (bckgnd)| | (bckgnd)|
- | | |+(icons) | | |
- +---------+ +---------+ +---------+
-
- The advantages of this approach is that it is straightforward, continual
- reading of the background is not needed, there is no flicker and it is
- simple to implement. The disadvantages are that two 64000 byte virtual
- screens are needed, and the procedure is not very fast because of the
- slow speed of flipping.
-
-
- METHOD 2 :
-
- Step 1 : Draw background to VGA.
- Step 2 : Grab portion of background that icon will be placed on.
- Step 3 : Place icon.
- Step 4 : Replace portion of background from Step 2 over icon.
- Step 5 : Repeat from step 2 continuously.
-
- In terms of ascii ...
-
- +---------+
- | +--|------- + Background restored (3)
- | * -|------> * Background saved to memory (1)
- | ^ |
- | +--|------- # Icon placed (2)
- +---------+
-
- The advantages of this method is that very little extra memory is
- needed. The disadvantages are that writing to VGA is slower then writing
- to memory, and there may be large amounts of flicker.
-
-
- METHOD 3 :
-
- Step 1 : Set up one virtual screen, VADDR.
- Step 2 : Draw background to VADDR.
- Step 3 : Flip VADDR to VGA.
- Step 4 : Draw icon to VGA.
- Step 5 : Transfer background portion from VADDR to VGA.
- Step 6 : Repeat from step 4 continuously.
-
- In ascii ...
-
- +---------+ +---------+
- | | | |
- | VGA | | VADDR |
- | | | (bckgnd)|
- | Icon>* <|-----------|--+ |
- +---------+ +---------+
-
- The advantages are that writing from the virtual screen is quicker then
- from VGA, and there is less flicker then in Method 2. Disadvantages are
- that you are using a 64000 byte virtual screen, and flickering occurs
- with large numbers of objects.
-
- In the attached sample program, a mixture of Method 3 and Method 1 is
- used. It is faster then Method 1, and has no flicker, unlike Method 3.
- What I do is I use VADDR2 for background, but only restore the
- background that has been changed to VADDR, before flipping to VGA.
-
- In the sample program, you will see that I restore the entire background
- of each of the icons, and then place all the icons. This is because if I
- replace the background then place the icon on each object individually,
- if two objects are overlapping, one is partially overwritten.
-
- The following sections are explanations of how the various assembler
- routines work. This will probably be fairly boring for you if you
- already know assembler, but should help beginners and dabblers alike.
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ The ASM Putpixel
-
- To begin with, I will explain a few of the ASM variables and functions :
-
- <NOTE THAT THIS IS AN EXTREMELY SIMPLISTIC VIEW OF ASSEMBLY LANGUAGE!
- There are numerous books to advance your knowledge, and the Norton
- Guides assembler guide may be invaluable for people beginning to code
- in assembler. I haven't given you the pretty pictures you are supposed
- to have to help you understand it easier, I have merely laid it out like
- a programming language with it's own special procedures. >
-
- There are 4 register variables : AX,BX,CX,DX. These are words (double
- bytes) with a range from 0 to 65535. You may access the high and low
- bytes of these by replacing the X with a "H" for high or "L" for low.
- For example, AL has a range from 0-255.
-
- You also have two pointers : ES:DI and DS:SI. The part on the left is
- the segment to which you are pointing (eg $a000), and the right hand
- part is the offset, which is how far into the segment you are pointing.
- Turbo Pascal places a variable over 16k into the base of a segment, ie.
- DI or SI will be zero at the start of the variable.
-
- If you wish to be pointing to pixel number 3000 on the VGA screen (see
- previous parts for the layout of the VGA screen), ES would be equal to
- $a000 and DI would be equal to 3000. You can quite as easily make ES or
- DS be equal to the offset of a virtual screen.
-
- Here are a few functions that you will need to know :
-
- mov destination,source This moves the value in source to
- destination. eg mov ax,50
- add destination,source This adds source to destination,
- the result being stored in destination
- mul source This multiplies AX by source. If
- source is a byte, the source is
- multiplied by AL, the result being
- stored in AX. If source is a word,
- the source is multiplied by AX, the
- result being stored in DX:AX
- movsb This moves the byte that DS:SI is
- pointing to into ES:DI, and
- increments SI and DI.
- movsw Same as movsb except it moves a
- word instead of a byte.
- stosw This moves AX into ES:DI. stosb
- moves AL into ES:DI. DI is then
- incremented.
- push register This saves the value of register by
- pushing it onto the stack. The
- register may then be altered, but
- will be restored to it's original
- value when popped.
- pop register This restores the value of a pushed
- register. NOTE : Pushed values must
- be popped in the SAME ORDER but
- REVERSED.
- rep command This repeats Command by as many
- times as the value in CX
-
-
- SHL Destination,count ;
- and SHR Destination,count ;
- need a bit more explaining. As you know, computers think in ones and
- zeroes. Each number may be represented in this base 2 operation. A byte
- consists of 8 ones and zeroes (bits), and have a range from 0 to 255. A
- word consists of 16 ones and zeroes (bits), and has a range from 0 to
- 65535. A double word consists of 32 bits.
-
- The number 53 may be represented as follows : 00110101. Ask someone who
- looks clever to explain to you how to convert from binary to decimal and
- vice-versa.
-
- What happens if you shift everything to the left? Drop the leftmost
- number and add a zero to the right? This is what happens :
-
- 00110101 = 53
- <-----
- 01101010 = 106
-
- As you can see, the value has doubled! In the same way, by shifting one
- to the right, you halve the value! This is a VERY quick way of
- multiplying or dividing by 2. (note that for dividing by shifting, we
- get the trunc of the result ... ie. 15 shr 1 = 7)
-
- In assembler the format is SHL destination,count This shifts
- destination by as many bits in count (1=*2, 2=*4, 3=*8, 4=*16 etc)
- Note that a shift takes only 2 clock cycles, while a mul can take up to 133
- clock cycles. Quite a difference, no? Only 286es or above may have count
- being greater then one.
-
- This is why to do the following to calculate the screen coordinates for
- a putpixel is very slow :
-
- mov ax,[Y]
- mov bx,320
- mul bx
- add ax,[X]
- mov di,ax
-
- But alas! I hear you cry. 320 is not a value you may shift by, as you
- may only shift by 2,4,8,16,32,64,128,256,512 etc.etc. The solution is
- very cunning. Watch.
-
- mov bx,[X]
- mov dx,[Y]
- push bx
- mov bx, dx {; bx = dx = Y}
- mov dh, dl {; dh = dl = Y}
- xor dl, dl {; These 2 lines equal dx*256 }
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1 {; bx = bx * 64}
- add dx, bx {; dx = dx + bx (ie y*320)}
- pop bx {; get back our x}
- add bx, dx {; finalise location}
- mov di, bx
-
- Let us have a look at this a bit closer shall we?
- bx=dx=y dx=dx*256 ; bx=bx*64 ( Note, 256+64 = 320 )
-
- dx+bx=Correct y value, just add X!
-
- As you can see, in assembler, the shortest code is often not the
- fastest.
-
- The complete putpixel procedure is as follows :
-
- Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
- { This puts a pixel on the screen by writing directly to memory. }
- BEGIN
- Asm
- push ds {; Make sure these two go out the }
- push es {; same they went in }
- mov ax,[where]
- mov es,ax {; Point to segment of screen }
- mov bx,[X]
- mov dx,[Y]
- push bx {; and this again for later}
- mov bx, dx {; bx = dx}
- mov dh, dl {; dx = dx * 256}
- xor dl, dl
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1
- shl bx, 1 {; bx = bx * 64}
- add dx, bx {; dx = dx + bx (ie y*320)}
- pop bx {; get back our x}
- add bx, dx {; finalise location}
- mov di, bx {; di = offset }
- {; es:di = where to go}
- xor al,al
- mov ah, [Col]
- mov es:[di],ah {; move the value in ah to screen
- point es:[di] }
- pop es
- pop ds
- End;
- END;
-
- Note that with DI and SI, when you use them :
- mov di,50 Moves di to position 50
- mov [di],50 Moves 50 into the place di is pointing to
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ The Flip Procedure
-
- This is fairly straightforward. We get ES:DI to point to the start of
- the destination screen, and DS:SI to point to the start of the source
- screen, then do 32000 movsw (64000 bytes).
-
- procedure flip(source,dest:Word);
- { This copies the entire screen at "source" to destination }
- begin
- asm
- push ds
- mov ax, [Dest]
- mov es, ax { ES = Segment of source }
- mov ax, [Source]
- mov ds, ax { DS = Segment of source }
- xor si, si { SI = 0 Faster then mov si,0 }
- xor di, di { DI = 0 }
- mov cx, 32000
- rep movsw { Repeat movsw 32000 times }
- pop ds
- end;
- end;
-
- The cls procedure works in much the same way, only it moves the color
- into AX then uses a rep stosw (see program for details)
-
- The PAL command is almost exactly the same as it's Pascal equivalent
- (see previous tutorials). Look in the sample code to see how it uses the
- out and in commands.
-
-
- =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- ■ In Closing
-
- The assembler procedures presented to you in here are not at their best.
- Most of these are procedures ASPHYXIA abandoned for better ones after
- months of use. But, as you will soon see, they are all MUCH faster then
- the original Pascal equivalents I originally gave you. In future, I
- hope to give you more and more assembler procedures for your ever
- growing collections. But, as you know, I am not always very prompt with
- this series (I don't know if even one has been released within one week
- of the previous one), so if you want to get any stuff done, try do it
- yourself. What do you have to lose, aside from your temper and a few
- rather inventive reboots ;-)
-
- What should I do for the next trainer? A simple 3-d tutorial? You may
- not like it, because I would go into minute detail of how it works :)
- Leave me suggestions for future trainers by any of the means discussed
- at the top of this trainer.
-
- After the customary quote, I will place a listing of the BBSes I
- currently know that regularly carry this Trainer Series. If your BBS
- receives it regularly, no matter where in the country you are, get a
- message to me and I'll add it to the list. Let's make it more convenient
- for locals to grab a copy without calling long distance ;-)
-
- [ There they sit, the preschooler class encircling their
- mentor, the substitute teacher.
- "Now class, today we will talk about what you want to be
- when you grow up. Isn't that fun?" The teacher looks
- around and spots the child, silent, apart from the others
- and deep in thought. "Jonny, why don't you start?" she
- encourages him.
- Jonny looks around, confused, his train of thought
- disrupted. He collects himself, and stares at the teacher
- with a steady eye. "I want to code demos," he says,
- his words becoming stronger and more confidant as he
- speaks. "I want to write something that will change
- peoples perception of reality. I want them to walk
- away from the computer dazed, unsure of their footing
- and eyesight. I want to write something that will
- reach out of the screen and grab them, making
- heartbeats and breathing slow to almost a halt. I want
- to write something that, when it is finished, they
- are reluctant to leave, knowing that nothing they
- experience that day will be quite as real, as
- insightful, as good. I want to write demos."
- Silence. The class and the teacher stare at Jonny, stunned. It
- is the teachers turn to be confused. Jonny blushes,
- feeling that something more is required. "Either that
- or I want to be a fireman."
- ]
- - Grant Smith
- 14:32
- 21/11/93
-
- See you next time,
- - DENTHOR
-
- These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
-
- ╔══════════════════════════╦════════════════╦═════╦═══╦════╦════╗
- ║BBS Name ║Telephone No. ║Open ║Msg║File║Past║
- ╠══════════════════════════╬════════════════╬═════╬═══╬════╬════╣
- ║ASPHYXIA BBS #1 ║(031) 765-5312 ║ALL ║ * ║ * ║ * ║
- ║ASPHYXIA BBS #2 ║(031) 765-6293 ║ALL ║ * ║ * ║ * ║
- ║Connectix BBS ║(031) 266-9992 ║ALL ║ * ║ * ║ * ║
- ║For Your Eyes Only BBS ║(031) 285-318 ║A/H ║ * ║ * ║ * ║
- ╚══════════════════════════╩════════════════╩═════╩═══╩════╩════╝
-
- Open = Open at all times or only A/H
- Msg = Available in message base
- File = Available in file base
- Past = Previous Parts available
-